//+------------------------------------------------------------------+
//|                                                   TrailingMA.mqh |
//|                             Copyright 2000-2025, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#include <Expert/ExpertTrailing.h>  // 移动止损基类（提供止损框架）

// wizard description start（MQL5 策略向导描述，用于识别类信息与参数）
//+------------------------------------------------------------------+
//| 类功能描述                                                       |
//| Title=基于移动平均线（MA）的移动止损（Trailing Stop）             |
//| Type=Trailing                                                    |
//| Name=MA                                                          |
//| Class=CTrailingMA                                                |
//| Page=                                                            |
//| Parameter=Period,int,12,MA计算周期（均线平滑周期，值越大趋势反应越慢） |
//| Parameter=Shift,int,0,MA偏移量（K线偏移，0=当前K线，1=前一根K线）   |
//| Parameter=Method,ENUM_MA_METHOD,MODE_SMA,均线计算方法（如SMA、EMA）  |
//| Parameter=Applied,ENUM_APPLIED_PRICE,PRICE_CLOSE,应用价格（计算MA的基础价格）|
//+------------------------------------------------------------------+
// wizard description end

//+------------------------------------------------------------------+
//| CTrailingMA 类：基于移动平均线（MA）的移动止损实现                 |
//| 核心能力：继承自 CExpertTrailing，通过跟踪移动平均线（MA）的位置，   |
//|           动态调整止损位，使止损跟随趋势方向移动，既锁定利润又给趋势留有余地 |
//| 核心逻辑：多单止损=MA值（随MA上移而提高），空单止损=MA值（随MA下移而降低）， |
//|           利用MA的趋势平滑特性，避免被短期波动触发止损，适合趋势跟踪策略   |
//| 适用场景：中长线趋势交易（MA能有效过滤短期噪音，反映中期趋势），适合股票、期货、外汇等 |
//|           品种，尤其适合趋势明确但波动较大的市场（如原油、黄金）         |
//+------------------------------------------------------------------+
class CTrailingMA : public CExpertTrailing
  {
protected:
   // 核心组件与参数（保护，子类可访问）
   CiMA             *m_MA;            // MA 指标对象（封装均线计算与数据读取）
   // MA 指标可调参数（与指标原生参数对应，默认配置平衡趋势跟踪与灵敏度）
   int               m_ma_period;     // 计算周期（默认12，值越大均线越平滑，趋势反应越慢）
   int               m_ma_shift;      // 偏移量（默认0，K线偏移数，1=使用前一根K线的MA值）
   ENUM_MA_METHOD    m_ma_method;     // 计算方法（默认MODE_SMA=简单移动平均，可选EMA=指数移动平均等）
   ENUM_APPLIED_PRICE m_ma_applied;   // 应用价格（默认PRICE_CLOSE=收盘价，可选最高价、最低价等）

public:
   //----------------------------------------------------------------
   // 构造与析构函数
   //----------------------------------------------------------------
   /**
    * @brief 构造函数：初始化基于 MA 的移动止损
    * @details 1. 初始化 MA 指标指针为 NULL（需在 InitIndicators 中创建）；
    *          2. 设置默认 MA 参数（周期=12，偏移=0，方法=SMA，应用价格=收盘价）；
    *          3. 继承父类 CExpertTrailing 的移动止损框架初始化
    */
                     CTrailingMA(void);

   /**
    * @brief 析构函数：清理基于 MA 的移动止损资源
    * @details 释放 MA 指标对象占用的内存，依赖父类析构逻辑完成止损框架资源清理
    */
                    ~CTrailingMA(void);

   //----------------------------------------------------------------
   // MA 指标参数配置：修改均线核心参数（外部调用接口）
   //----------------------------------------------------------------
   /**
    * @brief 设置 MA 计算周期（核心参数）
    * @param period [in] 周期值（需>0，建议10-50，值越大对短期波动过滤越强，趋势跟踪越稳定）
    */
   void              Period(int period);

   /**
    * @brief 设置 MA 偏移量（K线偏移）
    * @param shift [in] 偏移值（≥0，0=当前K线，1=前一根K线，用于延迟止损调整，降低敏感度）
    */
   void              Shift(int shift);

   /**
    * @brief 设置 MA 计算方法（平滑类型）
    * @param method [in] 计算方法（ENUM_MA_METHOD 枚举，如 MODE_SMA=简单平均，MODE_EMA=指数平均）
    * @note EMA 对近期价格更敏感，适合趋势初期；SMA 更平滑，适合趋势中期
    */
   void              Method(ENUM_MA_METHOD method);

   /**
    * @brief 设置 MA 应用价格（计算基础）
    * @param applied [in] 价格类型（ENUM_APPLIED_PRICE 枚举，如 PRICE_CLOSE=收盘价、PRICE_HIGH=最高价）
    */
   void              Applied(ENUM_APPLIED_PRICE applied);

   //----------------------------------------------------------------
   // 指标初始化：创建并注册 MA 指标（移动止损生效前提）
   //----------------------------------------------------------------
   /**
    * @brief 初始化 MA 指标及相关数据
    * @param indicators [in] 指标集合对象（用于管理所有策略用到的指标，如 MA、MACD 等）
    * @return bool - 初始化结果：true=成功（MA 创建+注册到指标集合），false=失败
    * @note 调用流程：
    *       1. 检查指标集合指针有效性；
    *       2. 创建 MA 指标对象（m_MA）并添加到指标集合；
    *       3. 调用 m_MA.Create() 绑定当前品种、周期及 MA 参数（周期、偏移、方法、应用价格）；
    *       4. 调整 MA 缓冲区大小以存储足够数据；
    *       5. 若创建或初始化失败，释放资源并返回 false
    */
   virtual bool      InitIndicators(CIndicators *indicators);

   //----------------------------------------------------------------
   // 参数验证：确保 MA 指标参数有效（移动止损生效前提）
   //----------------------------------------------------------------
   /**
    * @brief 验证 MA 指标参数的有效性
    * @return bool - 验证结果：true=所有参数有效，false=存在无效参数（如周期≤0）
    * @note 验证逻辑：
    *       1. 先调用父类 ValidationSettings() 验证基础框架参数（如品种、周期）；
    *       2. 额外验证 MA 计算周期（m_ma_period）是否>0，若无效则输出错误日志并返回false；
    *       3. 偏移量、计算方法、应用价格由类型限制，无需额外验证
    */
   virtual bool      ValidationSettings(void);

   //----------------------------------------------------------------
   // 移动止损核心逻辑：分别处理多单和空单的止损调整
   //----------------------------------------------------------------
   /**
    * @brief 检查多单（买入）的移动止损条件，计算新止损位
    * @param position [in] 持仓信息对象（包含开仓价、当前止损等数据）
    * @param sl [out] 新止损价（若满足条件则更新，否则为EMPTY_VALUE）
    * @param tp [out] 新止盈价（固定为EMPTY_VALUE，本类不调整止盈）
    * @return bool - 调整结果：true=已更新止损，false=未调整
    * @note 多单逻辑（利用 MA 跟踪上升趋势）：
    *       1. 安全阈值=当前卖价（Bid）- 平台最小止损点数×点值（避免止损过近触发）；
    *       2. 新止损价=前一根K线的 MA 值（m_MA.Main(1)），经价格精度标准化；
    *       3. 基准价=初始止损价（若未设置则用开仓价）；
    *       4. 触发条件：新止损价>基准价（确保止损上移）且新止损价<安全阈值（符合平台规则）；
    *       5. 满足条件则更新止损为 MA 值，随 MA 上移自动提高，锁定下方利润
    */
   virtual bool      CheckTrailingStopLong(CPositionInfo *position,double &sl,double &tp);

   /**
    * @brief 检查空单（卖出）的移动止损条件，计算新止损位
    * @param position [in] 持仓信息对象（包含开仓价、当前止损等数据）
    * @param sl [out] 新止损价（若满足条件则更新，否则为EMPTY_VALUE）
    * @param tp [out] 新止盈价（固定为EMPTY_VALUE，本类不调整止盈）
    * @return bool - 调整结果：true=已更新止损，false=未调整
    * @note 空单逻辑（利用 MA 跟踪下降趋势）：
    *       1. 安全阈值=当前买价（Ask）+ 平台最小止损点数×点值（避免止损过近触发）；
    *       2. 新止损价=前一根K线的 MA 值 + 点差×点值（补偿点差影响），经价格精度标准化；
    *       3. 基准价=初始止损价（若未设置则用开仓价）；
    *       4. 触发条件：新止损价<基准价（确保止损下移）且新止损价>安全阈值（符合平台规则）；
    *       5. 满足条件则更新止损为 MA 值，随 MA 下移自动降低，锁定上方利润
    */
   virtual bool      CheckTrailingStopShort(CPositionInfo *position,double &sl,double &tp);
  };
//+------------------------------------------------------------------+